package main

/**
1、切片:（是引用类型，所以不进行赋值的话，它的零值--默认值是--nil）

	1）与数组相同，可以容纳若干类型相同的元素的容器。但是切片类型可以确定值的长度。
	   每个切片值都会将数组作为底层数据结构。将这样的数组称为切片刀的底层数组。
	2）切片是对数组的一个连续片段的引用，所以切片是一个引用类型，这个片段可以是整个数组，
	   也可以是由起始和终止索引标识的一些项的子集，需要注意的是，终止索引标识的项不包括在切片内（意思是这是个左闭右开的区间）

2、对--len（长度）和 cap（容量）的理解：
	通俗理解：
			公司名：相当于字面量，就是变量名。
			公司所有的工位：相当于已分配到的内存空间
			公司的员工：相当于元素
			cap：代表这个公司最多可以容纳多少员工
			len：代表这个公司当前有多少员工

3、问题：对切片中容量的理解？？？？？？
*/
import "fmt"

func main() {

	myarr := [...]int{1, 2, 3}
	fmt.Printf("%d 的类型是：%T\n", myarr[0:2], myarr[0:2])
	fmt.Println("============================================")

	// 切片的构造方式（有4种）
	// 定义一个数组
	arr := [5]int{1, 2, 3, 4, 5}
	/**
	第1种：
	arr[1:3] （1表示从索引1开始，直到索引为2（3-1）的元素）
	*/
	slice_1 := arr[1:3]

	/**
	第2种：
	arr[1:3:4]（1表示从索引1开始，直到索引为2（3-1）的元素）
	4 的作用：在切片时，若不指定第三个数，那么切片终止索引会一直到原数组的最后一个数。
					 如果指定了第三个数，那么切片终止索引只会到原数组的该索引值。
	*/
	slice_2 := arr[1:3:4]
	fmt.Println("第1种：", slice_1)
	fmt.Println("第2种：", slice_2)
	fmt.Println("============================================")

	arrTest := [5]int{1, 2, 3, 4, 5}
	fmt.Printf("arrTest 的长度是：%d, 容量是： %d\n", len(arrTest), cap(arrTest))

	/**
	因为是[1:3]均表示索引值，从原数组中可以得出，从索引--0到3，索引容量大小是4
	*/
	myslice_1 := arrTest[1:3]
	fmt.Printf("myslice_1 的长度是：%d, 容量是： %d\n", len(myslice_1), cap(myslice_1))
	fmt.Println(myslice_1)

	/**
	因为是[1:3]均表示索引值,后面添加了一个4，表示从索引--1到3，索引的容量大小是3
	*/
	myslice_2 := arrTest[1:3:4]
	fmt.Printf("myslice_2 的长度是：%d, 容量是： %d\n", len(myslice_2), cap(myslice_2))
	fmt.Println(myslice_2)
	/**
	输出结果：
			arrTest 的长度是：5, 容量是： 5
			myslice_1 的长度是：2, 容量是： 4
			[2 3]
			myslice_2 的长度是：2, 容量是： 3
			[2 3]

	解释说明：切片的第3个数，影响的只是切片的容量，而不会影响长度
	*/
	fmt.Println("============================================")

	/**
	声明
	*/
	// 声明字符串切片
	var strList []string
	// 声明整型切片
	var numList []int
	// 声明一个空切片
	var numListEmpty = []int{}

	fmt.Println(strList)
	fmt.Println(numList)
	fmt.Println(numListEmpty)
	fmt.Println("============================================")

	/*
		使用make函数构造，格式：make([]Type, size, cap)
		切片三要素：
				类型（Type）、长度（size）、容量（cap）
	*/
	a := make([]int, 2)
	b := make([]int, 2, 10)
	fmt.Println(a, b)
	fmt.Println(len(a), len(b))
	fmt.Println(cap(a), cap(b))
	/**
	输出结果：
			[0 0] [0 0]
			2 2
			2 10
	*/
	fmt.Println("============================================")

	/**
	使用和数组一样，偷懒的方法
	*/
	slice_3 := []int{4: 2}
	fmt.Println(slice_3)
	fmt.Println(len(slice_3), cap(slice_3))
	/**
	输出结果：
			[0 0 0 0 2]
			5 5
	*/
	fmt.Println("============================================")

	/**
	使用append添加元素
	*/
	myslice_3 := []int{1}
	// 添加一个元素
	myslice_3 = append(myslice_3, 2)
	fmt.Println(myslice_3)
	// 添加一个切片， ...表示解包，不能省略
	myslice_3 = append(myslice_3, []int{7, 8}...)
	fmt.Println(myslice_3)
	// 在第一个位置插入元素
	myslice_3 = append([]int{9}, myslice_3...)
	fmt.Println(myslice_3)
	// 在中间插入一个切片（2个元素）
	//myslice_3 = append(myslice_3[:])
	/**
	输出结果：
			[1 2]
			[1 2 7 8]
			[9 1 2 7 8]
	*/
	fmt.Println("============================================")

	/*
		思考题：为什么 myslice 的长度为2，却能访问到第四个元素？

		解答：第一个输出结果是[5,6],因为 myslice := numbers4[4:6:8]，4和6表示的是索引值大小，所以包含索引4的值到索引6的值，不包含索引是6的值（即5和6）
			 第二个输出是8，由cap(myslice)可知，容量大小是8，因为myslice中的值是从索引4开始，即值5开始，所以，myslice = myslice[:cap(myslice)]
			 myslice的值是 [5,6,7,8] 其长度还是4，所以第4个元素是8
	*/
	var numbers4 = [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	// myslice中索引的值是从索引4开始的
	myslice := numbers4[4:6:8]
	fmt.Println("myslice的容量是：", cap(myslice))
	fmt.Printf("myslice为 %d, 其长度为: %d\n", myslice, len(myslice))

	myslice = myslice[:cap(myslice)]
	var num int = len(myslice)
	fmt.Println("myslice的长度是：", num)
	fmt.Printf("myslice的第四个元素为: %d", myslice[3])
	/**
	输出结果：
			myslice的容量是： 4
			myslice为 [5 6], 其长度为: 2
			myslice的长度是： 4
			myslice的第四个元素为: 8
	*/
}
